#pragma once

#include <unordered_map>
#include <utility>

#include "../reactor/Reactor.h"
#include "ClientConnection.h"
#include "ServerConnection.h"

namespace network {

    class TcpServer {

    public:

        using recvCallBack = ClientConnection::recvCallBack;

        using closeCallBack = ClientConnection::closeCallBack;

        using acceptCallBack = std::function<void(ClientConnection *)>;

        explicit TcpServer(recvCallBack recv_cb, unsigned int port = 8080,
                           Reactor *reactor = singleton::Singleton<Reactor>::getInstance());

        ~TcpServer();

        /**
          * @brief  启动服务端程序
          * @note   阻塞函数
          */
        void start();

        /**
          * @brief  停止服务端程序
          * @note   反应堆将被停止
          */
        void stop();

        /**
          * @brief  初始化Tcp服务端，进行绑定、监听、设置reactor模型处理器等
          * @note   start函数会调用init，请勿重复调用
          */
        void init();

        /**
          * @brief  设置客户端断开连接时的回调函数
          * @param  cb 回调函数
          */
        void setCloseCallBack(closeCallBack cb) { close_cb_ = std::move(cb); }

        /**
          * @brief  设置客户端建立连接时的回调函数
          * @param  cb 回调函数
          */
        void setAcceptCallBack(acceptCallBack cb) { accept_cb_ = std::move(cb); }

    private:

        // 服务端回调
        void serverHandler(int, EventType, void *);

        // 客户端回调
        void clientHandler(int, EventType, void *);

    private:

        // 服务端连接
        std::shared_ptr<ServerConnection> server_conn_;

        // 连接池（用来保持连接不被析构释放）
        std::unordered_map<int, std::shared_ptr<ClientConnection>> clients_;

        // 客户端收数据回调函数
        recvCallBack recv_cb_;

        // 客户端断开连接回调函数
        closeCallBack close_cb_;

        // 客户端建立连接回调函数
        acceptCallBack accept_cb_;

        // 反应堆指针
        Reactor *reactor_;

    };

}
